#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
抖音视频编码分析系统 - 主应用程序入口
整合所有模块，提供完整的视频分析流程
"""

import os
import sys
import json
import logging
import argparse
import datetime
import time
from typing import Dict, Any, List, Optional, Union
from pathlib import Path

# 设置根目录
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))

# 设置日志配置
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("logs/application.log"),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("DYVideoAnalysiser")


class ApplicationError(Exception):
    """
    应用程序异常基类
    """
    pass


class DYVideoAnalysiser:
    """
    抖音视频编码分析系统主类
    整合所有模块，提供完整的视频分析流程
    """
    
    def __init__(self):
        """
        初始化分析系统
        """
        self.app_name = "抖音视频编码分析系统"
        self.version = "1.0.0"
        self.initialized_at = datetime.datetime.now()
        
        # 模块实例
        self._config_manager = None
        self._vision_analyzer = None
        self._text_analyzer = None
        self._text_generator = None
        
        # 模块加载状态
        self._modules_loaded = False
        
        logger.info(f"{self.app_name} v{self.version} 初始化中...")
        
        # 加载环境变量
        self._load_environment()
        
        # 初始化目录结构
        self._initialize_directories()
    
    def _load_environment(self):
        """
        加载环境变量
        """
        try:
            from dotenv import load_dotenv
            
            # 尝试加载.env文件
            env_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".env")
            if os.path.exists(env_path):
                load_dotenv(env_path)
                logger.info(f"环境变量从 {env_path} 加载成功")
            else:
                logger.warning(f"未找到 .env 文件: {env_path}")
            
            # 验证必要的环境变量
            required_vars = [
                "ZHIPU_AI_API_KEY",
            ]
            
            missing_vars = []
            for var in required_vars:
                if not os.environ.get(var):
                    missing_vars.append(var)
            
            if missing_vars:
                logger.warning(f"缺少以下必要环境变量: {', '.join(missing_vars)}")
                logger.warning("请确保在 .env 文件中正确配置 API 密钥")
            
        except ImportError:
            logger.warning("未安装 python-dotenv，跳过环境变量加载")
        except Exception as e:
            logger.error(f"加载环境变量失败: {str(e)}")
    
    def _initialize_directories(self):
        """
        初始化必要的目录结构
        """
        try:
            app_root = os.path.dirname(os.path.abspath(__file__))
            
            # 定义需要创建的目录
            directories = [
                os.path.join(app_root, "data"),
                os.path.join(app_root, "data", "configs"),
                os.path.join(app_root, "data", "templates"),
                os.path.join(app_root, "data", "cache"),
                os.path.join(app_root, "output"),
                os.path.join(app_root, "output", "reports"),
                os.path.join(app_root, "output", "results"),
                os.path.join(app_root, "output", "temp"),
                os.path.join(app_root, "logs"),
            ]
            
            # 创建目录
            for directory in directories:
                os.makedirs(directory, exist_ok=True)
                logger.debug(f"目录已创建或存在: {directory}")
            
            logger.info("目录结构初始化完成")
            
        except Exception as e:
            logger.error(f"初始化目录结构失败: {str(e)}")
            raise ApplicationError(f"初始化目录结构失败: {str(e)}")
    
    def load_modules(self):
        """
        加载所有模块
        """
        try:
            # 加载配置模块
            from src.config import get_category_config_manager
            self._config_manager = get_category_config_manager()
            logger.info("配置模块加载成功")
            
            # 加载视觉分析模块
            from src.vision import get_vision_analysis_module
            self._vision_analyzer = get_vision_analysis_module()
            logger.info("视觉分析模块加载成功")
            
            # 加载文本分析模块
            from src.text import get_text_analysis_module
            self._text_analyzer = get_text_analysis_module()
            logger.info("文本分析模块加载成功")
            
            # 加载文本生成器模块
            from src.txt_generator import get_text_generator
            self._text_generator = get_text_generator()
            logger.info("文本生成器模块加载成功")
            
            self._modules_loaded = True
            logger.info("所有模块加载完成")
            
        except ImportError as e:
            logger.error(f"导入模块失败: {str(e)}")
            raise ApplicationError(f"导入模块失败: {str(e)}")
        except Exception as e:
            logger.error(f"加载模块失败: {str(e)}")
            raise ApplicationError(f"加载模块失败: {str(e)}")
    
    def analyze_video(self, 
                     video_path: str,
                     output_path: str = None,
                     generate_report: bool = True,
                     report_format: str = "markdown",
                     use_text_complement: bool = True,
                     max_frames: int = 5) -> Dict[str, Any]:
        """
        分析单个视频
        
        Args:
            video_path: 视频文件路径
            output_path: 输出路径
            generate_report: 是否生成报告
            report_format: 报告格式
            use_text_complement: 是否使用文本模型补充分析
            max_frames: 最大分析帧数
            
        Returns:
            Dict[str, Any]: 分析结果
        """
        try:
            # 检查模块加载状态
            if not self._modules_loaded:
                self.load_modules()
            
            # 验证视频文件
            if not os.path.exists(video_path):
                raise ApplicationError(f"视频文件不存在: {video_path}")
            
            if not os.path.isfile(video_path):
                raise ApplicationError(f"不是有效的视频文件: {video_path}")
            
            logger.info(f"开始分析视频: {video_path}")
            start_time = time.time()
            
            # 1. 视觉分析
            vision_analysis_result = self._vision_analyzer.analyze_video(
                video_path=video_path,
                max_frames=max_frames
            )
            
            # 2. 文本补充分析（如果启用）
            if use_text_complement:
                # 提取需要补充分析的类目（低置信度的结果）
                categories_to_complement = []
                for category in vision_analysis_result.get("category_results", []):
                    # 筛选置信度低于0.8的结果
                    if category.get("confidence", 0) < 0.8:
                        categories_to_complement.append(category["category_name"])
                
                if categories_to_complement:
                    logger.info(f"需要文本模型补充分析的类目: {categories_to_complement}")
                    
                    # 补充分析
                    text_complement_result = self._text_analyzer.complement_visual_analysis(
                        visual_result=vision_analysis_result,
                        categories=categories_to_complement
                    )
                    
                    # 合并结果
                    vision_analysis_result.update(text_complement_result)
            
            # 3. 添加分析元数据
            vision_analysis_result["analysis_time"] = time.time() - start_time
            vision_analysis_result["analysis_timestamp"] = datetime.datetime.now().isoformat()
            vision_analysis_result["analysis_version"] = self.version
            
            # 4. 保存分析结果
            result_file_path = None
            if output_path:
                result_file_path = self._save_analysis_result(
                    result=vision_analysis_result,
                    output_path=output_path,
                    video_path=video_path
                )
                vision_analysis_result["result_file_path"] = result_file_path
            
            # 5. 生成报告（如果启用）
            report_file_path = None
            if generate_report:
                report_file_path = self._text_generator.generate_and_save_report(
                    analysis_result=vision_analysis_result,
                    output_format=report_format
                )
                vision_analysis_result["report_file_path"] = report_file_path
            
            logger.info(f"视频分析完成: {video_path}")
            logger.info(f"  - 耗时: {vision_analysis_result['analysis_time']:.2f}秒")
            if result_file_path:
                logger.info(f"  - 结果文件: {result_file_path}")
            if report_file_path:
                logger.info(f"  - 报告文件: {report_file_path}")
            
            return vision_analysis_result
            
        except Exception as e:
            logger.error(f"分析视频失败: {str(e)}")
            raise ApplicationError(f"分析视频失败: {str(e)}")
    
    def _save_analysis_result(self, 
                            result: Dict[str, Any],
                            output_path: str,
                            video_path: str) -> str:
        """
        保存分析结果到文件
        """
        try:
            # 确定输出目录
            if os.path.isdir(output_path):
                # 如果是目录，生成文件名
                video_name = os.path.basename(video_path)
                video_name = os.path.splitext(video_name)[0]
                timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
                filename = f"{video_name}_analysis_result_{timestamp}.json"
                full_path = os.path.join(output_path, filename)
            else:
                # 如果是文件路径，直接使用
                full_path = output_path
            
            # 确保目录存在
            os.makedirs(os.path.dirname(full_path), exist_ok=True)
            
            # 保存结果
            with open(full_path, 'w', encoding='utf-8') as f:
                json.dump(result, f, ensure_ascii=False, indent=2)
            
            logger.info(f"分析结果已保存: {full_path}")
            return full_path
            
        except Exception as e:
            logger.error(f"保存分析结果失败: {str(e)}")
            raise ApplicationError(f"保存分析结果失败: {str(e)}")
    
    def batch_analyze_videos(self, 
                           video_paths: List[str],
                           output_dir: str,
                           generate_report: bool = True,
                           report_format: str = "markdown",
                           use_text_complement: bool = True,
                           max_frames: int = 5) -> List[Dict[str, Any]]:
        """
        批量分析多个视频
        
        Args:
            video_paths: 视频文件路径列表
            output_dir: 输出目录
            generate_report: 是否生成报告
            report_format: 报告格式
            use_text_complement: 是否使用文本模型补充分析
            max_frames: 最大分析帧数
            
        Returns:
            List[Dict[str, Any]]: 分析结果列表
        """
        try:
            # 检查模块加载状态
            if not self._modules_loaded:
                self.load_modules()
            
            # 确保输出目录存在
            os.makedirs(output_dir, exist_ok=True)
            
            # 创建结果和报告子目录
            results_dir = os.path.join(output_dir, "results")
            reports_dir = os.path.join(output_dir, "reports")
            os.makedirs(results_dir, exist_ok=True)
            os.makedirs(reports_dir, exist_ok=True)
            
            logger.info(f"开始批量分析视频，共 {len(video_paths)} 个视频")
            start_time = time.time()
            
            # 分析每个视频
            all_results = []
            success_count = 0
            failed_count = 0
            
            for idx, video_path in enumerate(video_paths):
                try:
                    logger.info(f"分析视频 {idx+1}/{len(video_paths)}: {video_path}")
                    
                    # 分析视频
                    result = self.analyze_video(
                        video_path=video_path,
                        output_path=results_dir,
                        generate_report=generate_report,
                        report_format=report_format,
                        use_text_complement=use_text_complement,
                        max_frames=max_frames
                    )
                    
                    all_results.append(result)
                    success_count += 1
                    
                except Exception as e:
                    logger.error(f"分析视频 {idx+1}/{len(video_paths)} 失败: {str(e)}")
                    failed_count += 1
                    
                    # 记录失败信息
                    failed_result = {
                        "video_path": video_path,
                        "status": "failed",
                        "error_message": str(e),
                        "timestamp": datetime.datetime.now().isoformat()
                    }
                    all_results.append(failed_result)
                    
            # 生成批处理摘要
            batch_summary = {
                "total_videos": len(video_paths),
                "success_count": success_count,
                "failed_count": failed_count,
                "total_time": time.time() - start_time,
                "timestamp": datetime.datetime.now().isoformat(),
                "version": self.version
            }
            
            # 保存摘要
            summary_path = os.path.join(output_dir, "batch_summary.json")
            with open(summary_path, 'w', encoding='utf-8') as f:
                json.dump(batch_summary, f, ensure_ascii=False, indent=2)
            
            logger.info(f"批量分析完成: {success_count}/{len(video_paths)} 成功")
            logger.info(f"  - 总耗时: {batch_summary['total_time']:.2f}秒")
            logger.info(f"  - 摘要文件: {summary_path}")
            
            return all_results
            
        except Exception as e:
            logger.error(f"批量分析失败: {str(e)}")
            raise ApplicationError(f"批量分析失败: {str(e)}")
    
    def validate_config(self) -> Dict[str, Any]:
        """
        验证系统配置
        
        Returns:
            Dict[str, Any]: 验证结果
        """
        try:
            # 检查模块加载状态
            if not self._modules_loaded:
                self.load_modules()
            
            validation_results = {
                "config": {},
                "environment": {},
                "modules": {}
            }
            
            # 验证配置模块
            config_validation = {
                "status": "success",
                "category_count": 0,
                "error": None
            }
            
            try:
                categories = self._config_manager.get_all_categories()
                config_validation["category_count"] = len(categories)
            except Exception as e:
                config_validation["status"] = "failed"
                config_validation["error"] = str(e)
            
            validation_results["config"] = config_validation
            
            # 验证环境变量
            env_validation = {
                "zhipu_api_key": "present" if os.environ.get("ZHIPU_AI_API_KEY") else "missing"
            }
            validation_results["environment"] = env_validation
            
            # 验证模块状态
            modules_validation = {
                "config_manager": "loaded" if self._config_manager else "failed",
                "vision_analyzer": "loaded" if self._vision_analyzer else "failed",
                "text_analyzer": "loaded" if self._text_analyzer else "failed",
                "text_generator": "loaded" if self._text_generator else "failed"
            }
            validation_results["modules"] = modules_validation
            
            # 整体状态
            all_success = (
                config_validation["status"] == "success" and
                env_validation["zhipu_api_key"] == "present" and
                all(value == "loaded" for value in modules_validation.values())
            )
            
            validation_results["overall_status"] = "success" if all_success else "partial"
            
            return validation_results
            
        except Exception as e:
            logger.error(f"验证配置失败: {str(e)}")
            raise ApplicationError(f"验证配置失败: {str(e)}")
    
    def get_system_info(self) -> Dict[str, Any]:
        """
        获取系统信息
        
        Returns:
            Dict[str, Any]: 系统信息
        """
        import platform
        import sys
        
        return {
            "app_name": self.app_name,
            "version": self.version,
            "python_version": sys.version,
            "platform": platform.platform(),
            "initialized_at": self.initialized_at.isoformat(),
            "modules_loaded": self._modules_loaded,
        }
    
    def shutdown(self):
        """
        关闭系统，释放资源
        """
        try:
            logger.info("系统正在关闭...")
            
            # 关闭各个模块
            if self._config_manager:
                try:
                    # 如果配置管理器有shutdown方法
                    if hasattr(self._config_manager, 'shutdown'):
                        self._config_manager.shutdown()
                except Exception as e:
                    logger.error(f"关闭配置管理器失败: {str(e)}")
            
            if self._vision_analyzer:
                try:
                    # 如果视觉分析器有shutdown方法
                    if hasattr(self._vision_analyzer, 'shutdown'):
                        self._vision_analyzer.shutdown()
                except Exception as e:
                    logger.error(f"关闭视觉分析器失败: {str(e)}")
            
            if self._text_analyzer:
                try:
                    # 如果文本分析器有shutdown方法
                    if hasattr(self._text_analyzer, 'shutdown'):
                        self._text_analyzer.shutdown()
                except Exception as e:
                    logger.error(f"关闭文本分析器失败: {str(e)}")
            
            if self._text_generator:
                try:
                    # 如果文本生成器有shutdown方法
                    if hasattr(self._text_generator, 'shutdown'):
                        self._text_generator.shutdown()
                except Exception as e:
                    logger.error(f"关闭文本生成器失败: {str(e)}")
            
            logger.info("系统已成功关闭")
            
        except Exception as e:
            logger.error(f"关闭系统失败: {str(e)}")


def parse_arguments():
    """
    解析命令行参数
    """
    parser = argparse.ArgumentParser(description='抖音视频编码分析系统')
    
    # 子命令
    subparsers = parser.add_subparsers(dest='command', help='可用命令')
    
    # 分析单个视频命令
    analyze_parser = subparsers.add_parser('analyze', help='分析单个视频文件')
    analyze_parser.add_argument('video_path', help='视频文件路径')
    analyze_parser.add_argument('--output', '-o', help='输出结果文件路径')
    analyze_parser.add_argument('--no-report', action='store_true', help='不生成报告')
    analyze_parser.add_argument('--format', '-f', default='markdown', choices=['markdown', 'txt'], help='报告格式')
    analyze_parser.add_argument('--no-text-complement', action='store_true', help='不使用文本模型补充分析')
    analyze_parser.add_argument('--max-frames', type=int, default=5, help='最大分析帧数')
    
    # 批量分析命令
    batch_parser = subparsers.add_parser('batch', help='批量分析多个视频文件')
    batch_parser.add_argument('video_paths', nargs='+', help='视频文件路径列表')
    batch_parser.add_argument('--output-dir', '-o', required=True, help='输出目录')
    batch_parser.add_argument('--no-report', action='store_true', help='不生成报告')
    batch_parser.add_argument('--format', '-f', default='markdown', choices=['markdown', 'txt'], help='报告格式')
    batch_parser.add_argument('--no-text-complement', action='store_true', help='不使用文本模型补充分析')
    batch_parser.add_argument('--max-frames', type=int, default=5, help='最大分析帧数')
    
    # 验证配置命令
    validate_parser = subparsers.add_parser('validate', help='验证系统配置')
    
    # 获取系统信息命令
    info_parser = subparsers.add_parser('info', help='获取系统信息')
    
    return parser.parse_args()


def main():
    """
    主函数
    """
    try:
        # 解析命令行参数
        args = parse_arguments()
        
        # 创建应用实例
        app = DYVideoAnalysiser()
        
        try:
            # 根据命令执行相应操作
            if args.command == 'analyze':
                # 分析单个视频
                result = app.analyze_video(
                    video_path=args.video_path,
                    output_path=args.output,
                    generate_report=not args.no_report,
                    report_format=args.format,
                    use_text_complement=not args.no_text_complement,
                    max_frames=args.max_frames
                )
                
                # 打印结果摘要
                print(json.dumps(result, ensure_ascii=False, indent=2))
                
            elif args.command == 'batch':
                # 批量分析视频
                results = app.batch_analyze_videos(
                    video_paths=args.video_paths,
                    output_dir=args.output_dir,
                    generate_report=not args.no_report,
                    report_format=args.format,
                    use_text_complement=not args.no_text_complement,
                    max_frames=args.max_frames
                )
                
                # 打印摘要信息
                print(f"批量分析完成，共分析 {len(results)} 个视频")
                success_count = sum(1 for r in results if r.get('status') != 'failed')
                print(f"成功: {success_count}, 失败: {len(results) - success_count}")
                
            elif args.command == 'validate':
                # 验证配置
                validation_result = app.validate_config()
                print(json.dumps(validation_result, ensure_ascii=False, indent=2))
                
                # 检查整体状态
                if validation_result['overall_status'] != 'success':
                    sys.exit(1)
                    
            elif args.command == 'info':
                # 获取系统信息
                info = app.get_system_info()
                print(json.dumps(info, ensure_ascii=False, indent=2))
                
            else:
                # 如果没有指定命令，显示帮助信息
                print("请指定命令")
                print("可用命令: analyze, batch, validate, info")
                sys.exit(1)
                
        finally:
            # 关闭应用
            app.shutdown()
            
    except KeyboardInterrupt:
        print("\n程序被用户中断")
        sys.exit(1)
    except Exception as e:
        print(f"错误: {str(e)}")
        sys.exit(1)


if __name__ == '__main__':
    main()